/**
 * @apiDefine User
 */
const jwt = require('jsonwebtoken')
const bcrypt = require('bcryptjs')
const db = require('../models')
const config = require('../config/auth.config')

const { user: User, role: Role, refreshToken: RefreshToken } = db

const { Op } = db.Sequelize

/**
 * @api {post} user/register 注册
 * @apiName PostRegister
 * @apiGroup 用户模块
 * @apiUse User
 * @apiVersion 1.0.0
 *
 * @apiBody {String} username 用户名
 * @apiBody {String} password  密码
 * @apiBody {String} mobilephone  手机号
 * @apiBody {String} [nickname]  昵称
 * @apiBody {String} [truename]  真实姓名
 * @apiBody {String} [email]  邮箱
 * @apiBody {String} [introduction]  个人简介
 *
 * @apiSuccessExample 返回值
 *     {
 *       "errcode": 0,
 *       "message": "注册成功！",
 *       "result": ""
 *     }
 */
exports.signup = (req, res) => {
  // Save User to Database
  // console.log('>>>>>>> ', req.body.roles === undefined)
  User.create({
    username: req.body.username,
    email: req.body.email,
    password: bcrypt.hashSync(req.body.password, 8)
  })
    .then((user) => {
      if (req.body.roles) {
        Role.findAll({
          where: {
            name: {
              [Op.or]: req.body.roles
            }
          }
        }).then((roles) => {
          user.setRoles(roles).then(() => {
            res.send({ message: 'User was registered successfully!' })
          })
        })
      } else {
        // user role = 1
        user.setRoles([1]).then(() => {
          res.send({ message: 'User was registered successfully!' })
        })
      }
    })
    .catch((err) => {
      res.status(500).send({ message: err.message })
    })
}

/**
 * @api {POST} path 接口描述
 * @apiDescription 接口描述
 * @apiGroup AccountController
 * @apiHeader {String} key=desc
 * @apiParam {type} name desc
 *
 * @apiParamExample {json} 请求示例:
 * {
 *
 * }
 * @apiSuccessExample {json} 成功响应:
 * HTTP/1.1 200 OK
 * {
 *   "code":"0",
 *   "desc":"success",
 *   "data":{
 *
 *    }
 * }
 * @apiVersion 1.0.0
 */
exports.signin = (req, res) => {
  User.findOne({
    where: {
      username: req.body.username
    }
  })
    .then(async (user) => {
      if (!user) {
        return res.status(404).send({ message: 'User Not found.' })
      }

      const passwordIsValid = bcrypt.compareSync(req.body.password, user.password)

      if (!passwordIsValid) {
        return res.status(401).send({
          accessToken: null,
          message: 'Invalid Password!'
        })
      }
      const token = jwt.sign({ id: user.id }, config.secret, {
        expiresIn: config.jwtExpiration
      })
      const refreshToken = await RefreshToken.createToken(user)
      const authorities = []
      user.getRoles().then((roles) => {
        for (let i = 0; i < roles.length; i += 1) {
          authorities.push(`ROLE_${roles[i].name.toUpperCase()}`)
        }
        res.status(200).send({
          id: user.id,
          username: user.username,
          email: user.email,
          roles: authorities,
          accessToken: token,
          refreshToken
        })
      })
      return undefined
    })
    .catch((err) => {
      res.status(500).send({ message: err.message })
    })
}

/**
 * @api {POST} /api/auth/refreshToken 刷新token令牌
 * @apiDescription 刷新token令牌
 * @apiGroup Auth
 * @apiHeader {String} key=desc
 * @apiParam {type} refreshToken 请求令牌
 *
 * @apiParamExample {json} 请求示例:
 * {
 *    "refreshToken":"dasad"
 * }
 * @apiSuccessExample {json} 成功响应:
 * HTTP/1.1 200 OK
 * {
 *   "code":"0",
 *   "desc":"success",
 *   "data":{
 *
 *    }
 * }
 * @apiVersion 1.0.0
 */
exports.refreshToken = async (req, res) => {
  const { refreshToken: requestToken } = req.body

  if (requestToken == null) {
    return res.status(403).json({ message: 'Refresh Token is required!' })
  }

  try {
    const refreshToken = await RefreshToken.findOne({ where: { token: requestToken } })

    console.log(refreshToken)

    if (!refreshToken) {
      res.status(403).json({ message: 'Refresh token is not in database!' })
      return undefined
    }

    if (RefreshToken.verifyExpiration(refreshToken)) {
      RefreshToken.destroy({ where: { id: refreshToken.id } })

      res.status(403).json({
        message: 'Refresh token was expired. Please make a new signin request'
      })
      return undefined
    }

    const user = await refreshToken.getUser()
    const newAccessToken = jwt.sign({ id: user.id }, config.secret, {
      expiresIn: config.jwtExpiration
    })

    return res.status(200).json({
      accessToken: newAccessToken,
      refreshToken: refreshToken.token
    })
  } catch (err) {
    return res.status(500).send({ message: err })
  }
}

exports.verifyCodeSms = async (req, res) => {}
